#include <iostream>
#include <event2/event.h>
#include <event2/http.h>
#include <event2/bufferevent.h>
//#include <event2/keyvalq_struct.h>
#include <event2/buffer.h>
#ifndef _WIN32
#include <signal.h>
#endif
#include <string.h>
#include <string>
using namespace std;

void http_client_cb(struct evhttp_request *request, void *arg){
        cout<<"http client"<<endl;
        event_base *base = (event_base *)arg;
        //服务端响应错误
        if(request == NULL){
                int errcode = EVUTIL_SOCKET_ERROR();
                cout<<"socket error:"<<evutil_socket_error_to_string(errcode);
                return;
        }

        //获取path
        const char *path = evhttp_request_get_uri(request);
        cout<<"request path is " << path<<endl;
        string filepath = ".";
        filepath+="/download";
        filepath += path;
        cout<<"filepath is  "<<filepath<<endl;
        
        //如果路径有目录,需要分析出目录，并创建
        FILE *fp = fopen(filepath.c_str(), "wb");
        if(!fp){
                cout<<"open file " <<filepath<<" failed"<<endl;
        }

        //获取返回的code 200 404
        cout<<"Response : "<<evhttp_request_get_response_code(request); //200
        cout<<" "<<evhttp_request_get_response_code_line(request)<<endl;

        evbuffer *input = evhttp_request_get_input_buffer(request);
        char buf[1024] = {0};
        for (; ; ){
                int len = evbuffer_remove(input, buf, sizeof(buf)-1);
                if(len <= 0) break;
                //cout<<buf<<flush;
                if(!fp)
                        continue;
                fwrite(buf, 1, len, fp);
        }

        if(fp)
                fclose(fp);

        event_base_loopbreak(base);

        return;
}

int TestGetHttp(){
        event_base *base = event_base_new();

        // 生成请求信息
        string http_url = "http://localhost:8080/index.html?id=1";
        http_url = "http://localhost:8080/douyin.png";
        http_url = "http://localhost:8080/index.html";
        // 分析url地址
        // uri 
        evhttp_uri *uri = evhttp_uri_parse(http_url.c_str());
        // http https
        const char *scheme = evhttp_uri_get_scheme(uri);
        if(!scheme){
                cerr<<"scheme is null"<<endl;
                return -1;
        }
        cout<<"scheme is "<<scheme<<endl; 

        //port
        int port  = evhttp_uri_get_port(uri);
        if(port < 0){
                if(strcmp(scheme, "http") == 0){
                        port = 80;
                }
                if(strcmp(scheme, "https") == 0){
                        port = 443;
                }
        }
        cout<<"port is "<<port<<endl;

        //host
        const char *host = evhttp_uri_get_host(uri);  
        if(!host){
                cerr<<"host is null"<<endl;
                return -1;
        }
        cout<<"host is "<<host<<endl;
        
        const char *path = evhttp_uri_get_path(uri);
        if(!path || strlen(path) == 0){
                path = "/";
        }
        if(path){
                cout<<"path is "<<path <<endl;
        }

        const char *query = evhttp_uri_get_query(uri);
        if(query){
                cout<<"query is "<<query<<endl;
        }else{
                cout<<"query is null" <<endl;
        }

        //bufferevent 连接http服务器
        bufferevent *bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);
        evhttp_connection *evcon = evhttp_connection_base_bufferevent_new(base, NULL, bev, host, port);
        
        //http client 请求 回调函数设置
        evhttp_request *req = evhttp_request_new(http_client_cb, base);

        //设置请求的head 消息报头 信息
        evkeyvalq *output_headers = evhttp_request_get_output_headers(req);
        evhttp_add_header(output_headers, "Host", host);

        //发起请求 evcon本质Tcp传输层协议 req本质http应用层协议
        evhttp_make_request(evcon, req, EVHTTP_REQ_GET, path);

        event_base_dispatch(base);

        event_base_free(base);
        return 0;
}

int TestPostHttp(){
        event_base *base = event_base_new();

        // 生成请求信息
        string http_url = "http://localhost:8080/index.html";
        http_url = "http://localhost:8080/douyin.png";
        http_url = "http://localhost:8080/index.html";
        // 分析url地址
        // uri 
        evhttp_uri *uri = evhttp_uri_parse(http_url.c_str());
        // http https
        const char *scheme = evhttp_uri_get_scheme(uri);
        if(!scheme){
                cerr<<"scheme is null"<<endl;
                return -1;
        }
        cout<<"scheme is "<<scheme<<endl; 

        //port
        int port  = evhttp_uri_get_port(uri);
        if(port < 0){
                if(strcmp(scheme, "http") == 0){
                        port = 80;
                }
                if(strcmp(scheme, "https") == 0){
                        port = 443;
                }
        }
        cout<<"port is "<<port<<endl;

        //host
        const char *host = evhttp_uri_get_host(uri);  
        if(!host){
                cerr<<"host is null"<<endl;
                return -1;
        }
        cout<<"host is "<<host<<endl;
        
        const char *path = evhttp_uri_get_path(uri);
        if(!path || strlen(path) == 0){
                path = "/";
        }
        if(path){
                cout<<"path is "<<path <<endl;
        }

        const char *query = evhttp_uri_get_query(uri);
        if(query){
                cout<<"query is "<<query<<endl;
        }else{
                cout<<"query is null" <<endl;
        }

        //bufferevent 连接http服务器
        bufferevent *bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);
        evhttp_connection *evcon = evhttp_connection_base_bufferevent_new(base, NULL, bev, host, port);
        
        //http client 请求 回调函数设置
        evhttp_request *req = evhttp_request_new(http_client_cb, base);

        //设置请求的head 消息报头 信息
        evkeyvalq *output_headers = evhttp_request_get_output_headers(req);
        evhttp_add_header(output_headers, "Host", host);

        //发送post数据
        evbuffer *output =  evhttp_request_get_output_buffer(req);
        evbuffer_add_printf(output, "xcj=%d&b=%d", 1, 2);


        //发起请求 evcon本质Tcp传输层协议 req本质http应用层协议
        evhttp_make_request(evcon, req, EVHTTP_REQ_POST, path);

        event_base_dispatch(base);

        event_base_free(base);
        return 0;
}

int main(int argc, char const *argv[]){
#ifdef _WIN32
        //初始化socket库
        WSADATA wsa;
        WSAStartup(MAKEWORD(2,2), &wsa);
#else
        //忽略管道信号 发送数据给已关闭的socket
        if(signal(SIGPIPE,SIG_IGN) == SIG_IGN){
                return 1;
        }
#endif  

       TestGetHttp();
       
       TestPostHttp();

        return 0;
}
 